﻿/* 
 * About: This ExpandableGroupBox control is a C# adaptation of code posted by Nick Thissen
 *        on http://www.vbforums.com/showthread.php?t=576403.
 */

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace DotNetNukeMVPWizard
{
    [Designer(typeof(ExpandableGroupboxDesigner))]
    public partial class ExpandableGroupBox : UserControl
    {
        #region User Control Designer (Inner Class)
        /// <summary>
        /// Designer class that enables the user to expand/collapse the <see cref="ExpandableGroupbox" /> control during Design-Time.
        /// </summary>
        /// <remarks></remarks>
        public class ExpandableGroupboxDesigner : System.Windows.Forms.Design.ParentControlDesigner
        {
            public override void Initialize(System.ComponentModel.IComponent component)
            {
                base.Initialize(component);

                //Add an event handler for the button click event so we can update the control
                Button btnExpand = ((ExpandableGroupBox)this.Control).ExpandButton;
                btnExpand.Click += ExpandButtonClicked;
            }

            public void ExpandButtonClicked(object sender, EventArgs ev)
            {
                //Tell the designer to update the control
                //If we don't do this, the selection rectangle would not update
                this.RaiseComponentChanged(TypeDescriptor.GetProperties(this.Control)["Size"], null, null);
            }

            //This function enables us to click the button during design-time
            protected override bool GetHitTest(System.Drawing.Point point)
            {
                Button btnExpand = ((ExpandableGroupBox)this.Control).ExpandButton;
                if ((btnExpand.Bounds.Contains(this.Control.PointToClient(point))))
                {
                    return true;
                }
                return base.GetHitTest(point);
            }
        }
        #endregion

        /// <summary>
        /// Fired when the control is Expanded or Collapsed.
        /// </summary>
        public event EventHandler Expand;

        #region " Properties "
        //public Button ExpandButton
        //{
        //    get
        //    {
        //        return this.ExpandButton;
        //    }
        //}

        private string _Caption;
        /// <summary>
        /// The text shown as the caption of the <see cref="ExpandableGroupbox" />.
        /// </summary>
        [Browsable(true)]
        public string Caption
        {
            get { return _Caption; }
            set
            {
                _Caption = value;
                this.lblCaption.Text = value;
            }
        }
        /// <summary>
        /// The color of the custom-drawn rounded border.
        /// </summary>
        [DefaultValue(typeof(Color), "214, 213, 217")]
        public Color BorderColor { get; set; }

        private bool _Expanded;
        /// <summary>
        /// True when the control is expanded.
        /// </summary>
        [DefaultValue(true)]
        public bool Expanded
        {
            get { return _Expanded; }
            set
            {
                _Expanded = value;

                //Make sure we set the size correctly
                this.OnExpand();
            }
        }

        private Color _CaptionColor;
        /// <summary>
        /// The ForeColor of the text shown as the caption of the <see cref="ExpandableGroupbox" />.
        /// </summary>
        [DefaultValue(typeof(Color), "51, 94, 168")]
        public Color CaptionColor
        {
            get { return _CaptionColor; }
            set
            {
                _CaptionColor = value;

                this.lblCaption.ForeColor = value;
            }
        }

        private Size _ExpandedSize;
        /// <summary>
        /// The Size of the <see cref="ExpandableGroupbox" /> when expanded. Should be set by resizing the control in the designer as usual.
        /// </summary>
        [Browsable(false), DefaultValue(typeof(Size), "200, 100")]
        public Size ExpandedSize
        {
            get { return _ExpandedSize; }
            set { _ExpandedSize = value; }
        }

        private bool _HeaderClickExpand;
        /// <summary>
        /// If True, expands / collapses the control when the header (caption) is clicked, instead of using the button only.
        /// </summary>
        [DefaultValue(false)]
        public bool HeaderClickExpand
        {
            get { return _HeaderClickExpand; }
            set { _HeaderClickExpand = value; }
        }

        #endregion

        #region " Constructor "
        public ExpandableGroupBox()
        {
            Paint += pnlContainer_Paint;
            // This call is required by the Windows Form Designer.
            InitializeComponent();

            // Add any initialization after the InitializeComponent() call.
            this.BorderColor = Color.FromArgb(214, 213, 217);
            this.Expanded = true;
            this.CaptionColor = Color.FromArgb(51, 94, 168);
            this.HeaderClickExpand = true;

            this.Size = new Size(200, 100);

            this.lblCaption.Text = this.Caption;
            this.lblCaption.ForeColor = this.CaptionColor;
        }
        #endregion

        #region " Methods "

        /// <summary>
        /// Changes the Size property of the control when it is expanded/collapsed.
        /// </summary>
        /// <remarks></remarks>
        public virtual void OnExpand()
        {
            if (this.Expanded)
            {
                this.Size = this.ExpandedSize;
            }
            else
            {
                this.Size = pnlHeader.Size;
            }
        }

        #endregion

        #region " Events "
        private void ExpandButton_Click(object sender, EventArgs e)
        {
            //Toggle the expansion
            this.Expanded = !this.Expanded;

            //Repaint the button
            ExpandButton.Invalidate();

            //Repaint the header
            pnlHeader.Invalidate();

            if (Expand != null)
            {
                Expand(this, EventArgs.Empty);
            }
        }

        //Makes sure we can't drag the control out when it is collapsed
        protected override void OnResize(System.EventArgs e)
        {
            base.OnResize(e);

            if (this.Expanded)
            {
                this.ExpandedSize = this.Size;
            }
            else
            {
                if (this.DesignMode)
                {
                    this.Size = pnlHeader.Size;
                    this.ExpandedSize = new Size(this.Size.Width, this.ExpandedSize.Height);
                }
            }
        }

        private void pnlHeader_Click(object sender, EventArgs e)
        {
            if (this.HeaderClickExpand)
                ExpandButton.PerformClick();
        }

        private void lblCaption_Click(object sender, EventArgs e)
        {
            if (this.HeaderClickExpand)
                ExpandButton.PerformClick();
        }
        #endregion

        #region " Drawing "

        private void pnlHeader_Paint(System.Object sender, System.Windows.Forms.PaintEventArgs e)
        {
            using (Pen borderPen = new Pen(this.BorderColor, 1))
            {
                //Right of button/text
                e.Graphics.DrawLine(borderPen, this.lblCaption.Left + this.lblCaption.Width + 10, 11, this.Width - 4, 11);
                if (this.Expanded)
                {
                    e.Graphics.DrawLine(borderPen, this.Width - 4, 12, this.Width - 3, 12);
                    e.Graphics.DrawLine(borderPen, this.Width - 3, 13, this.Width - 2, 13);
                    e.Graphics.DrawLine(borderPen, this.Width - 2, 14, this.Width - 2, this.Height);
                }

                //Left of button
                e.Graphics.DrawLine(borderPen, 4, 11, 7, 11);
                if (this.Expanded)
                {
                    e.Graphics.DrawLine(borderPen, 3, 12, 4, 12);
                    e.Graphics.DrawLine(borderPen, 2, 13, 3, 13);
                    e.Graphics.DrawLine(borderPen, 2, 14, 2, this.Height);
                }
            }
        }

        private void pnlContainer_Paint(System.Object sender, System.Windows.Forms.PaintEventArgs e)
        {
            using (Pen borderPen = new Pen(this.BorderColor, 1))
            {
                //e.Graphics.DrawLine(borderPen, 2, 0, 2, pnlPadding.Height - 4)
                //e.Graphics.DrawLine(borderPen, Me.Width - 2, 0, Me.Width - 2, pnlPadding.Height - 4)

                //e.Graphics.DrawLine(borderPen, 4, pnlPadding.Height - 1, pnlPadding.Width - 4, pnlPadding.Height - 1)

                //e.Graphics.DrawLine(borderPen, 3, pnlPadding.Height - 2, 4, pnlPadding.Height - 2)
                //e.Graphics.DrawLine(borderPen, 2, pnlPadding.Height - 3, 3, pnlPadding.Height - 3)

                //e.Graphics.DrawLine(borderPen, Me.Width - 4, pnlPadding.Height - 2, Me.Width - 3, pnlPadding.Height - 2)
                //e.Graphics.DrawLine(borderPen, Me.Width - 3, pnlPadding.Height - 3, Me.Width - 2, pnlPadding.Height - 3)

                e.Graphics.DrawLine(borderPen, 2, 0, 2, this.Height - 4);
                e.Graphics.DrawLine(borderPen, this.Width - 2, 0, this.Width - 2, this.Height - 4);

                e.Graphics.DrawLine(borderPen, 4, this.Height - 1, this.Width - 4, this.Height - 1);

                e.Graphics.DrawLine(borderPen, 3, this.Height - 2, 4, this.Height - 2);
                e.Graphics.DrawLine(borderPen, 2, this.Height - 3, 3, this.Height - 3);

                e.Graphics.DrawLine(borderPen, this.Width - 4, this.Height - 2, this.Width - 3, this.Height - 2);
                e.Graphics.DrawLine(borderPen, this.Width - 3, this.Height - 3, this.Width - 2, this.Height - 3);
            }
        }

        private void ExpandButton_Paint(System.Object sender, System.Windows.Forms.PaintEventArgs e)
        {
            e.Graphics.DrawLine(Pens.Black, 5, ExpandButton.Height / 2, ExpandButton.Width - 6, ExpandButton.Height / 2);
            if (!this.Expanded)
            {
                e.Graphics.DrawLine(Pens.Black, ExpandButton.Width / 2, 5, ExpandButton.Width / 2, ExpandButton.Height - 6);
            }
        }

        #endregion

        private void ExpandableGroupBox_Load(object sender, EventArgs e)
        {

        }
    }
}
